package com.zh.kotlin_mvvm.utils

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable
import android.widget.ImageView
import androidx.collection.LruCache
import androidx.core.view.doOnDetach
import com.blankj.utilcode.util.LogUtils
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions
import com.liulishuo.filedownloader.FileDownloader
import com.zh.common.listener.DownloadFileListener
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import java.io.File
import java.io.FileInputStream
import java.lang.ref.SoftReference

/**
 * 显示加密图片-需要自己释放bitmap
 */
class XyGlideUtils {
    companion object {
        val mMemoryCache by lazy {
            // 获取最大可用内存
            val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
            // 设置缓存大小为最大可用内存的 2/8
            val cacheSize = maxMemory * 2 / 8
            object : LruCache<String?, Bitmap>(cacheSize) {
                override fun sizeOf(key: String, bitmap: Bitmap): Int {
                    // 返回每张图片占用的字节数
                    return bitmap.byteCount / 1024
                }
            }
        }
        val instance by lazy {
            FileDownloader.getImpl().setMaxNetworkThreadCount(6)
            XyGlideUtils()
        }
    }

    fun addBitmapToMemoryCache(key: String, bitmap: Bitmap) {
        if (getBitmapFromMemCache(key) == null) {
            mMemoryCache.put(key, bitmap)
        }
    }

    fun getBitmapFromMemCache(key: String): Bitmap? {
        return mMemoryCache[key]
    }
}

/**
 * 加载图片
 *
 * @param url                地址
 * @param imageView          控件
 * @param defaultError       加载错误默认图片
 * @param defaultPlaceholder 预加载图片
 * @param requestListener    状态监听
 */
private fun loadPicUrl(
    url: Any, imageView: ImageView, defaultError: Int,
    defaultPlaceholder: Int, requestListener: RequestListener<Drawable>? = null
) {
    val options = RequestOptions()
        .error(defaultError)
        .placeholder(defaultPlaceholder)
    SoftReference(imageView).get()?.let { it1 ->
        Glide.with(imageView)
            .asDrawable()
            .load(url)
            .apply(options)
            .listener(requestListener)
            .into(it1)
    }
}

fun Bitmap?.goRecycled() {
    this?.let {
        try {
            if (!it.isRecycled) {
                it.recycle()
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }
}

/**
 * 加载图片
 */
fun ImageView.loadUrl(
    url: Any, defaultRes: Int = 0, pos: Int = -1,
    back: ((Pair<Bitmap, Int>) -> Unit?)? = null
) {
    try {
        if (url is String && url.contains("-ssl")
            && XyGlideUtils.instance.getBitmapFromMemCache(url) != null
        ) {
            val imgBitmap = XyGlideUtils.instance.getBitmapFromMemCache(url)
            if (back == null) {
                setImageBitmap(imgBitmap)
            } else {
                back.invoke(Pair(imgBitmap!!, pos))
            }
            return
        }
        if (url is String && url.contains("-ssl")) {//加密图片
            XyGlideUtils.instance
            setImageResource(defaultRes)
            val file = File(this.context.externalCacheDir, "images")
            try {
                if (!file.exists()) {
                    file.mkdirs()
                }
                val filePath = File(file, url.substringAfterLast("/"))
                if (filePath.exists()) {
                    if (filePath.length() == 0L) {
                        filePath.delete()
                    } else {
                        this.loadSslImage(
                            url, filePath.absolutePath, defaultRes, 0, pos, back
                        )
                        return
                    }
                }
                this.downSslImage(url, filePath, defaultRes, 0, pos, back)
            } catch (e: Throwable) {
                e.printStackTrace()
            }
        } else {
            loadPicUrl(url, this, defaultRes, defaultRes)
        }
    } catch (e: Throwable) {
        e.printStackTrace()
    }
}

private fun ImageView.downSslImage(
    url: String, filePath: File, defaultRes: Int = 0, count: Int,
    pos: Int = -1, back: ((Pair<Bitmap, Int>) -> Unit?)? = null
) {
    downloadFile(url, filePath, object : DownloadFileListener {
        override fun success(path: String) {
            if (filePath.absolutePath == path)
                this@downSslImage.loadSslImage(url, path, defaultRes, count, pos, back)
        }

        override fun error(error: String) {
            super.error(error)
            downSslImage(url, filePath, defaultRes, 1 + count, pos, back)
        }
    })
}

private fun ImageView.loadSslImage(
    url: String, filePath: String, defaultRes: Int = 0, count: Int,
    pos: Int = -1, back: ((Pair<Bitmap, Int>) -> Unit?)? = null
) {
    val mainScope = MainScope()
    try {
        var isLoadSuc = false
        val imgByte = filePath.decodeIMGFile2String(url)
        if (imgByte.isNotEmpty()) {
//            LogUtils.d("图片", "url-> $url", "filePath-> $filePath")
            val imgBitmap = BitmapFactory.decodeByteArray(imgByte, 0, imgByte.size)
            imgBitmap?.let { bit ->
                this.post {
                    isLoadSuc = true
                    XyGlideUtils.instance.addBitmapToMemoryCache(url, imgBitmap)
                    if (back == null) {
                        setImageBitmap(imgBitmap)
                    } else {
                        back.invoke(Pair(imgBitmap, pos))
                    }
                    /*doOnDetach {
                        try {
                            if (!bit.isRecycled) bit.recycle()
                        } catch (e: Throwable) {
                            e.printStackTrace()
                        }
                    }*/
                }
            }
            if (imgBitmap == null) {
                LogUtils.d("图片 $url 加载失败 - imgByte = ${imgByte.size}")
                val file = File(filePath)
                if (file.exists()) file.delete()
            }
        }
        this.postDelayed({
            if (!isLoadSuc && count < 100) {
                val file = File(filePath)
                if (file.exists() && file.length() > 0) {
                    loadSslImage(url, filePath, defaultRes, count + 1, pos, back)
                } else {
                    downSslImage(url, file, defaultRes, count + 1, pos, back)
                }
            }
        }, 3000)
    } catch (e: Throwable) {
        e.printStackTrace()
    } finally {
        mainScope.cancel()
    }
}

/**
 * 保存文件
 * @param url 下载地址
 * @param path 文件地址
 * @param listener 下载进度监听
 */
private fun downloadFile(url: String, path: File, listener: DownloadFileListener) {
    try {
        val task = FileDownloader.getImpl().create(url).setPath(path.parentFile?.path, true)
        task.addFinishListener {
            if (path.exists() && path.length() > 0) {
                FileDownloader.getImpl().clear(task.id, "")
                task.removeFinishListener { }
                listener.success(path.absolutePath)
            } else {
//                listener.error("下载错误")
                if (task.isUsing) {
                    task.reuse()
                }
                task.start()
            }
        }
        task.autoRetryTimes = 10
        task.setMinIntervalUpdateSpeed(500)
        task.isForceReDownload = true
        task.start()
    } catch (e: Exception) {
        e.printStackTrace()
        listener.error("下载错误")
    }
}

/**
 * 解密图片文件
 */
private fun String?.decodeIMGFile2String(url: String): ByteArray {
    var inputFile: FileInputStream? = null
    try {
        if (!this.isNullOrEmpty() && File(this).exists()) {
            inputFile = FileInputStream(this)
            val buffer = ByteArray(inputFile.available())
            inputFile.read(buffer)
            val len = buffer.size
            val mask: Byte = buffer[0]
            val temp = ByteArray(len)
            for (i in 1 until len) {
                temp[i - 1] = (buffer[i].toInt() xor mask.toInt()).toByte()
            }
            return temp
        } else {
            LogUtils.d("图片 $url 下载失败")
        }
    } catch (e: Throwable) {
        e.printStackTrace()
    } finally {
        inputFile?.close()
    }
    return ByteArray(0)
}